/* cloud_detect.h */

#ifndef DODO_CLOUD_DETECT_H
#define DODO_CLOUD_DETECT_H


namespace quigon
{

class Cloud_Detect
{
public:
	enum 
	{  
		SINGLE = 0x1,
		REPEAT = 0x2,
		DIFF   = 0x4,
		STRICT = 0x8000,
		CLEAN_UP = 0x10000
	};

	Cloud_Detect(int start_index0, 
		double value_thres_single0, double value_thres_repeat0, double diff_thres0, 
		unsigned int option0
		) :
		start_index(start_index0), 
		value_thres_single(value_thres_single0),
		value_thres_repeat(value_thres_repeat0),
		diff_thres(diff_thres0),
		option(option0)
	{
	}
	Cloud_Detect(const std::string &filename, unsigned int option0) : option(option0)
	{
		Serie<std::string, double> para(filename);
		start_index = para["start_index"];
		if(option & SINGLE)
			value_thres_single = para["value_thres_single"];
		if(option & REPEAT)
			value_thres_repeat = para["value_thres_repeat"];
		if(option & DIFF)
			diff_thres = para["diff_thres"];
	}

	template<class TLine>
	int operator() (TLine &line)
	{
		for(size_t i = start_index; i < line.size(); ++i)
		{
			bool judgement = false;
			bool judge_single = false;
			bool judge_repeat = false;
			bool judge_diff = false;

			if( (option & SINGLE) && (line[i] > value_thres_single) )
			{
				judge_single = true;
			}
			if( (option & REPEAT) && 
				(i > start_index) &&
				(line[i] > value_thres_repeat) && (line[i - 1] > value_thres_repeat) )
			{
				judge_repeat = true;
			}
			if( (option & DIFF) && 
				(i > start_index) &&
				(line[i] - line[i - 1] > diff_thres))
			{
				judge_diff = true;
			}
				
			if(option & STRICT) // set to cloud only when all conditions are met
			{
				if(!(option & SINGLE))
					judge_single = true;
				if(!(option & REPEAT))
					judge_repeat = true;
				if(!(option & DIFF))
					judge_diff = true;

				judgement = judge_single && judge_repeat && judge_diff;

			}
			else // set to cloud when one of the conditions is met
			{
				judgement = judge_single || judge_repeat || judge_diff;
			}

			if(judgement)
			{
				if(option & CLEAN_UP)
				{
					for(size_t j = i + 1; j < line.size(); ++j)
					{
						line[j] = 0;
					}
				}
				return i;
			}

		}
		return 0;
	}
private:
	size_t start_index;
	double value_thres_single;
	double value_thres_repeat;
	double diff_thres;

	unsigned int option;
};

}

#endif

